package com.niiwoo.civet.account.service.dubbo.bill;

import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fastjson.JSON;
import com.niiwoo.civet.account.dao.entity.NiiwooBillExample;
import com.niiwoo.civet.account.dao.entity.NiiwooBillExampleExt;
import com.niiwoo.civet.account.dao.mapper.NiiwooBillMapperExt;
import com.niiwoo.civet.account.dto.bill.GroupBillAmountBySecondSubjectResponeDTO;
import com.niiwoo.civet.account.dto.request.StatisticUserBillAmountRequestDTO;
import com.niiwoo.civet.account.dto.response.GroupAmountByDayResponseDTO;
import com.niiwoo.civet.account.dto.response.GroupAmountByMonthResponseDTO;
import com.niiwoo.civet.account.dto.response.StatisticUserBillAmountReponseDTO;
import com.niiwoo.civet.account.enums.BillAmountStatisticsEnum;
import com.niiwoo.civet.account.enums.BillStatusEnum;
import com.niiwoo.civet.account.enums.GroupUserBillAmountTypeEnum;
import com.niiwoo.civet.account.service.bill.UserBillStatisticsDubboService;
import com.niiwoo.civet.account.service.local.bill.NiiwooBillService;
import com.niiwoo.civet.base.enums.ChannelCodeEnum;
import com.niiwoo.tripod.base.utils.DateUtils;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 用户账单统计
 * Created by xiaoyingping on 2018/11/7.
 */
@Service(version = "1.0.0")
@Slf4j
public class UserBillStatisticsDubboServiceImpl implements UserBillStatisticsDubboService {

    @Autowired
    private NiiwooBillMapperExt niiwooBillMapperExt;
    @Autowired
    private NiiwooBillService niiwooBillService;

    @Override
    public BigDecimal statisticUserBillAmount(StatisticUserBillAmountRequestDTO requestDTO) {
        long startTime = System.currentTimeMillis();
        log.info("dubbo interface start, interfaceName:statisticUserBillAmount, request:{}", JSON.toJSONString(requestDTO));

        //判断查询条件
        String userId = requestDTO.getUserId();
        Assert.hasLength(userId,"userId不能为空");
        BillAmountStatisticsEnum billAmountStatisticsEnum = requestDTO.getBillAmountStatisticsEnum();
        Assert.notNull(billAmountStatisticsEnum,"billAmountStatisticsEnum不能为空");

        //查询用户的账单科目金额汇总
        NiiwooBillExample example = this.generateNiiwooBillExample(requestDTO);
        List<GroupBillAmountBySecondSubjectResponeDTO> responeDTOList = niiwooBillService.groupAmountBySecondSubject(example);
        log.info("responeDTOList:{}", JSON.toJSONString(responeDTOList));

        //统计金额
        BigDecimal totalAmount = niiwooBillMapperExt.sumAmountByExample(example);
        log.info("dubbo interface end, costTime:{} ms, interfaceName:statisticUserBillAmount, request:{}, response:{}", System.currentTimeMillis() - startTime, JSON.toJSONString(requestDTO), totalAmount);
        return totalAmount;
    }

    @Override
    public List<StatisticUserBillAmountReponseDTO> statisticUserBillAmounts(StatisticUserBillAmountRequestDTO requestDTO) {
        long startTime = System.currentTimeMillis();
        log.info("dubbo interface start, interfaceName:statisticUserBillAmounts, request:{}", JSON.toJSONString(requestDTO));

        //判断查询条件
        String userId = requestDTO.getUserId();
        Assert.hasLength(userId,"userId不能为空");

        List<BillAmountStatisticsEnum> billAmountStatisticsEnums = requestDTO.getBillAmountStatisticsEnums();
        Assert.notEmpty(billAmountStatisticsEnums,"billAmountStatisticsEnums不能为空");

        //查询用户的账单科目金额汇总
        NiiwooBillExample example = this.generateNiiwooBillExample(requestDTO);
        List<GroupBillAmountBySecondSubjectResponeDTO> billAmountDTOList = niiwooBillService.groupAmountBySecondSubject(example);

        //分组统计金额
        List<StatisticUserBillAmountReponseDTO> result = new ArrayList<>();
        for (BillAmountStatisticsEnum billAmountStatisticsEnum : billAmountStatisticsEnums) {
            List<String> secondSubjects = BillAmountStatisticsEnum.getBillSecondSubjects(billAmountStatisticsEnum);
                    BigDecimal totalAmount = billAmountDTOList.stream()
                    .filter(e -> secondSubjects.contains(e.getBillSecondSubject()))
                    .map(e -> e.getAmount())
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            if(Objects.isNull(totalAmount)){
                totalAmount = BigDecimal.ZERO;
            }

            StatisticUserBillAmountReponseDTO dto = new StatisticUserBillAmountReponseDTO();
            dto.setBillAmountStatisticsEnum(billAmountStatisticsEnum);
            dto.setAmount(totalAmount);
            result.add(dto);
        }

        log.info("dubbo interface end, costTime:{} ms, interfaceName:statisticUserBillAmounts, request:{}, response:{}", System.currentTimeMillis() - startTime, JSON.toJSONString(requestDTO), JSON.toJSONString(result));
        return result;
    }

    /**
     * 按月分组
     */
    @Override
    public List<GroupAmountByMonthResponseDTO> groupAmountByMonthForYear(String userId, String year, GroupUserBillAmountTypeEnum amountType) {
        long startTime = System.currentTimeMillis();
        log.info("dubbo interface start, interfaceName:groupAmountByMonthForYear, userId:{},year:{}, amountType:{}",  userId, year, amountType);

        //设置查询的时间范围
        DateTime yearDateTime = new DateTime(DateUtils.parseDateFromString(year, "yyyy"));
        DateTime minDateTime = yearDateTime.withDayOfYear(1).withTimeAtStartOfDay();//年初第一天
        DateTime maxDateTime = minDateTime.plusYears(1).minusSeconds(1);//年末最后一天

        //查询账单列表
        NiiwooBillExample example = new NiiwooBillExample();
        NiiwooBillExample.Criteria criteria = example.createCriteria();
        criteria.andUserIdEqualTo(userId);
        criteria.andCreateTimeBetween(minDateTime.toDate(), maxDateTime.toDate());
        criteria.andSecondSortCodeIn(BillAmountStatisticsEnum.getBillSecondSubjects(BillAmountStatisticsEnum.EARNED_PROFIT_INVEST));
        List<GroupAmountByMonthResponseDTO> result = niiwooBillMapperExt.groupAmountByMonth(example);

        log.info("dubbo interface end, costTime:{} ms, interfaceName:groupAmountByMonthForYear, userId:{},year:{}, amountType:{}", System.currentTimeMillis() - startTime,  userId, year, amountType);
        return result;
    }


    /**
     * 按天分组
     * @param userId     用户id
     * @param month
     * @param amountType 需要统计的金额类型
     * @return
     */
    @Override
    public List<GroupAmountByDayResponseDTO> groupAmountByDayForMonth(String userId, String month, GroupUserBillAmountTypeEnum amountType) {
        long startTime = System.currentTimeMillis();
        log.info("dubbo interface start, interfaceName:groupAmountByDayForMonth, userId:{},month:{}, amountType:{}", userId, month, amountType);

        //设置查询的时间范围
        DateTime yearMonthDateTime = new DateTime(DateUtils.parseDateFromString(month, "yyyyMM"));
        DateTime minDateTime = yearMonthDateTime.withDayOfMonth(1).withTimeAtStartOfDay();//月初第一天
        DateTime maxDateTime = minDateTime.plusMonths(1).minusSeconds(1);//月末最后一天

        //查询账单列表
        NiiwooBillExample example = new NiiwooBillExample();
        NiiwooBillExample.Criteria criteria = example.createCriteria();
        criteria.andUserIdEqualTo(userId);
        criteria.andCreateTimeBetween(minDateTime.toDate(), maxDateTime.toDate());
        criteria.andSecondSortCodeIn(BillAmountStatisticsEnum.getBillSecondSubjects(BillAmountStatisticsEnum.EARNED_PROFIT_INVEST));
        List<GroupAmountByDayResponseDTO> result = niiwooBillMapperExt.groupAmountByDay(example);
        //result = result.stream().sorted(Comparator.comparing(GroupAmountByDayResponseDTO::getDay)).collect(Collectors.toList());

        //返回
        log.info("dubbo interface end, costTime:{} ms, interfaceName:groupAmountByDayForMonth, userId:{},month:{}, amountType:{}", System.currentTimeMillis() - startTime, userId, month, amountType);
        return result;
    }
    
    /**
     * 指定一天
     * @param userId     用户id
     * @param day
     * @param amountType 需要统计的金额类型
     * @return
     */
    public GroupAmountByDayResponseDTO groupAmountOneDay(String userId, String day, GroupUserBillAmountTypeEnum amountType) {
        long startTime = System.currentTimeMillis();
        log.info("dubbo interface start, interfaceName:{}, userId:{}, day:{}, amountType:{}", "groupAmountOneDay", userId, day, amountType);

        //设置查询的时间范围
        DateTime yearMonthDayDateTime = new DateTime(DateUtils.parseDateFromString(day, "yyyyMMdd"));
        DateTime minDateTime = yearMonthDayDateTime;//每天的开始时间
        DateTime maxDateTime = minDateTime.plusDays(1).minusSeconds(1);//每天的结束时间

        //查询账单列表
        NiiwooBillExample example = new NiiwooBillExample();
        NiiwooBillExample.Criteria criteria = example.createCriteria();
        criteria.andUserIdEqualTo(userId);
        criteria.andCreateTimeBetween(minDateTime.toDate(), maxDateTime.toDate());
        criteria.andSecondSortCodeIn(BillAmountStatisticsEnum.getBillSecondSubjects(BillAmountStatisticsEnum.EARNED_PROFIT_INVEST));
        BigDecimal amount = niiwooBillMapperExt.sumAmountByExample(example);

        //返回
        GroupAmountByDayResponseDTO result = new GroupAmountByDayResponseDTO();
        result.setDay(day);
        result.setAmount(amount);

        log.info("dubbo interface end, costTime:{} ms, interfaceName:{}, userId:{}, day:{}, amountType:{}", System.currentTimeMillis() - startTime, "groupAmountOneDay", userId, day, amountType);
        return result;
    }


    private NiiwooBillExampleExt generateNiiwooBillExample(StatisticUserBillAmountRequestDTO requestDTO) {
        Assert.notNull(requestDTO, "requestDTO不能为空");
        String userId = requestDTO.getUserId();
        Assert.hasLength(userId, "userId不能为空");

        NiiwooBillExampleExt niiwooBillExample = new NiiwooBillExampleExt();
        NiiwooBillExample.Criteria criteria = niiwooBillExample.createCriteria();
        criteria.andUserIdEqualTo(userId);
        criteria.andChannelCodeEqualTo(ChannelCodeEnum.APP.getChanelCode());
        criteria.andStatusEqualTo(BillStatusEnum.SUCCESS.getValue());

        if(Objects.nonNull(requestDTO.getBillAmountStatisticsEnum())){
            criteria.andSecondSortCodeIn(BillAmountStatisticsEnum.getBillSecondSubjects(requestDTO.getBillAmountStatisticsEnum()));
        }
        if(Objects.nonNull(requestDTO.getInvestId())){
            criteria.andInvestIdEqualTo(requestDTO.getInvestId());
        }
        if(!CollectionUtils.isEmpty(requestDTO.getInvestIds())){
            criteria.andInvestIdIn(requestDTO.getInvestIds());
        }
        if (Objects.nonNull(requestDTO.getBeginTime()) && Objects.nonNull(requestDTO.getEndTime())) {
            criteria.andCreateTimeBetween(requestDTO.getBeginTime(), requestDTO.getEndTime());
        }

        return niiwooBillExample;
    }


}
